#pragma once

enum xstrCompareBehavior
{
	xstrCompareCaseSensitive = 0x0,
	xstrCompareCaseInsensitive = 0x1,
};



/* 1883 */
struct XSTRING
{
	XUINT32 cString;
	XCHAR aString[1];
};


/* 1848 */
struct XSTRING_BASE
{
	XUINT32 cString;
	XCHAR * pString;
	XUINT32 flags;
//protected:
//	static void * operator new(XUINT32 cSize);
};


class CXString :
	public XSTRING_BASE
{
public: 
	struct XSTRING_EXTRA:
		public XSTRING_BASE
	{
		XUINT32 cchBufferLength;
		XCHAR achConnectedBuffer[1];
	};

	CXString();
	CXString(const struct XSTRING_BASE & rXSTRING);
	CXString(XUINT32 cchString, XCHAR * pchString);
	static void operator delete(void * ptr);
	~CXString();
	static CXString * Create(XUINT32 cch, XBOOL bPublic);
	static HRESULT CreateFromUInt32(XUINT32 value, CXString * * ppstrValue);
	static HRESULT CreateFromInt32(XINT32 value, CXString * * ppstrValue);
	static CXString * WrapBuffer(XCHAR * pchSource, XUINT32 cchValid, XUINT32 cchBufferLength, XBOOL bTakeOwnership);
	static CXString * WrapBuffer(XUINT32 cchValid, XCHAR * pchSource);
	CXString * Clone(XBOOL bConnectedBuffer, XBOOL bTrimBuffer) const;
	static CXString * CloneBuffer(const XCHAR * pchSource, XUINT32 cchValid);
	static CXString * CloneBuffer(const XCHAR * pchSource, XUINT32 cchValid, XUINT32 cchBufferLength, XINT32 bPublic);
	static CXString * CloneBufferTrimWhitespace(XCHAR * pchSource, XUINT32 cchValid);
	static CXString * Concatenate(const CXString & pstrFront, XUINT32 ichFrontStart, const CXString & pstrBack, XUINT32 ichBackStart);
	static CXString * Concatenate(const CXString * pstrFront, XUINT32 ichFrontStart, const CXString * pstrBack, XUINT32 ichBackStart);
	static CXString * EmptyString();
	static CXString * NullString();
	CXString * SubString(const XUINT32 startIndex, const XUINT32 endIndex) const;

	HRESULT Insert(const XCHAR * pchSource, XUINT32, XUINT32);
	HRESULT Insert(const CXString * pstrSource, XUINT32, XUINT32, XUINT32);
	HRESULT Insert(const CXString * pstrSource, XUINT32, XUINT32);
	HRESULT Insert(const CXString * pstrSource, XUINT32);

	HRESULT Remove(XUINT32 ichStart, XUINT32 cchRemove);
	HRESULT Append(const XCHAR * pchSource, XUINT32 cchAppend);
	HRESULT Append(const CXString * pstrSource, XUINT32, XUINT32, XUINT32);
	HRESULT Append(const CXString * pstrSource, XUINT32, XUINT32);
	HRESULT Append(const CXString * pstrSource, XUINT32 cchAppend);
	HRESULT Append(const CXString * rSource);
	HRESULT Append(const CXString & rSource);
	HRESULT AppendChar(XCHAR chSource);
	HRESULT Find(const CXString * pstrSource, XUINT32 ichStartingIndex, enum xstrCompareBehavior eCompareBehavior, XUINT32 * pichFound) const;
	HRESULT Find(const CXString * pstrSource, enum xstrCompareBehavior eCompareBehavior, XUINT32 * pichFound) const;
	HRESULT Find(const CXString * pstrSource, enum xstrCompareBehavior eCompareBehavior, XUINT32 * pichFound);
	HRESULT Find(const CXString * pstrSource, XUINT32 * pichFound);
	HRESULT FindChar(const XCHAR ch, XUINT32 * pichFound) const;
	HRESULT FindChar(const XCHAR ch, XUINT32 ichStartingIndex, XUINT32 * pichFound) const;
	HRESULT FindLastChar(const XCHAR ch, XUINT32 * pichFound);
	HRESULT FindLastChar(const XCHAR ch, XUINT32 ichStartingIndex, XUINT32 * pichFound) const;
	HRESULT Replace(const XCHAR oldChar, const XCHAR newChar);
	XINT32 StartsWith(const CXString * pstrStringToFind, enum xstrCompareBehavior eCompareBehavior) const;
	XINT32 EndsWith(const CXString & pstrStringToFind, enum xstrCompareBehavior eCompareBehavior) const;
	XINT32 EndsWith(const CXString * pstrStringToFind, enum xstrCompareBehavior eCompareBehavior) const;
	HRESULT ReplaceAtEnd(const CXString * pstrOld, const CXString * pstrNew, enum xstrCompareBehavior eCompareBehavior, CXString * * ppStr);
	XBOOL IsAllWhitespace();
	XBOOL Equals(const CXString & rstrSource, enum xstrCompareBehavior eCompareBehavior) const;
	XBOOL Equals(const CXString * rstrSource, enum xstrCompareBehavior eCompareBehavior) const;
	XCHAR GetChar(XUINT32 ichIndex) const;
	XINT32 Compare(const CXString & rstrSource, XUINT32 ichStartingIndex, XUINT32 cchCompare, enum xstrCompareBehavior eCompareBehavior) const;
	XINT32 Compare(const CXString * rstrSource, XUINT32 ichStartingIndex, XUINT32 cchCompare, enum xstrCompareBehavior eCompareBehavior) const;
	XINT32 Compare(const CXString * pstrSource, XUINT32 ichStartingIndex, enum xstrCompareBehavior eCompareBehavior);
	XINT32 Compare(const CXString * pstrSource, enum xstrCompareBehavior eCompareBehavior) const;
	XINT32 CompareChar(const XCHAR ch, XUINT32 ichStartingIndex, enum xstrCompareBehavior eCompareBehavior) const;
	void DebugValidate() const;
	XUINT32 GetCount() const;
	HRESULT SetCount(XUINT32);
	XCHAR * GetBuffer() const;
	CXString * GetPtr();
	XCHAR * RelinquishBuffer();
	XCHAR * MakeBufferCopy();
	HRESULT CopyToBuffer(XCHAR * * ppchTarget, XUINT32 * pcch);
	HRESULT Trim(XUINT32 toLength);
	static XBOOL NullOrEmpty(const CXString * pstrString);
	XUINT32 BufferLength() const;
	static CXString * CharToWideChar(XUINT32 cstr, char * pstr);
	char * WideCharToChar(XUINT32 * pcstr, char * pstrDest);
private: 
	const XCHAR * GetConstBuffer() const;
	void InitializeBuffer(XUINT32 cchBuffer);
	void InitializeWrappedBuffer(XCHAR * pchSource, XUINT32 cchValid, XUINT32 cchBufferLength, XUINT32 bTakeOwnership);

	HRESULT InsertPrivate(const XCHAR *, XUINT32, XUINT32);
	HRESULT InsertPrivate(const CXString *, XUINT32, XUINT32, XUINT32);

	HRESULT AppendPrivate(const XCHAR * pchSource, XUINT32 cchSource, XUINT32 ichTargetIndex);
	HRESULT AppendPrivate(const CXString & rSource, XUINT32 ichTargetIndex, XUINT32 ichSourceIndex, XUINT32 cchSource);
	HRESULT AppendPrivate(const CXString * rSource, XUINT32 ichTargetIndex, XUINT32 ichSourceIndex, XUINT32 cchSource);
	XBOOL OwnsBuffer() const;
	XBOOL IsConnectedBuffer();
	XUINT32 BufferLengthRemaining();
	XBOOL IsStaticEmptyString();
	XCHAR * ApplyOwnerFlag(XCHAR * pch);
	XCHAR * MaskOffOwnerFlag(XCHAR * pch);
};

